#requires –version 2.0

function Invoke-Patching {
	#region Parameters
	
		param
(
			[Parameter(Mandatory=$true)][array]$HostList,
			[Parameter(Mandatory=$true)][string]$Assets,
			[Parameter(Mandatory=$true)][string]$ScriptVersion,
			[Parameter(Mandatory=$true)][string]$JobLogFullName,
			[Parameter(Mandatory=$true)][string]$SubScripts,
			[Parameter(Mandatory=$false)][string]$vCenter,
			[Parameter(Mandatory=$true)][string]$MinFreeMB,
			[Parameter(Mandatory=$true)][string]$UserDomain,
			[Parameter(Mandatory=$true)][string]$UserName,
			[Parameter(Mandatory=$true)][string]$ScriptHost,
			[Parameter(Mandatory=$true)][string]$FileDateTime,
			[Parameter(Mandatory=$true)][string]$LogPath,
			[Parameter(Mandatory=$true)][int]$MaxJobs,
			[Parameter(Mandatory=$true)][int]$JobQueTimeout,
			[Parameter(Mandatory=$true)][string]$ResultsTextFullName,
			[Parameter(Mandatory=$false)][boolean]$UseAltViCredsBool = $false,
			[Parameter(Mandatory=$false)][boolean]$UseAltPCCredsBool = $false,
			[Parameter(Mandatory=$false)]$ViCreds,
			[Parameter(Mandatory=$false)]$PCCreds,
			[Parameter(Mandatory=$true)][int]$TotalHosts,
			[Parameter(Mandatory=$true)][int]$DashCount,
			[Parameter(Mandatory=$true)][string]$ScriptTitle,
			[Parameter(Mandatory=$false)][boolean]$SkipDiskSpaceCheckBool = $false,
			[Parameter(Mandatory=$false)][boolean]$SkipVMHardwareBool = $false,
			[Parameter(Mandatory=$false)][boolean]$SkipVMToolsBool = $false,
			[Parameter(Mandatory=$false)][boolean]$SkipAllVmwareBool = $false
		)

	#endregion Parameters
	
	#region Functions

		# EXTERNAL
		. "$SubScripts\Func_Get-Runtime_1.0.3.ps1"
		. "$SubScripts\Func_Remove-Jobs_1.0.5.ps1"
		. "$SubScripts\Func_Get-JobCount_1.0.3.ps1"
		. "$SubScripts\Func_Watch-Jobs_1.0.3.ps1"
		. "$SubScripts\Func_Show-ScriptHeader_1.0.2.ps1"
		. "$SubScripts\MultiFunc_Set-WinTitle_1.0.5.ps1"
			# Set-WinTitle-Start
			# Set-WinTitle-Base
			# Set-WinTitle-Input
			# Set-WinTitle-JobCount
			# Set-WinTitle-JobTimeout
			# Set-WinTitle-Completed
		. "$SubScripts\MultiFunc_Out-ScriptLog_1.0.3.ps1"
			# Out-ScriptLog-Header
			# Out-ScriptLog-Starttime
			# Out-ScriptLog-Error
			# Out-ScriptLog-JobTimeout
			# Out-ScriptLog-Footer
		. "$SubScripts\MultiFunc_Show-Script-Status_1.0.3.ps1"
			# Show-ScriptStatus-StartInfo
			# Show-ScriptStatus-QueuingJobs
			# Show-ScriptStatus-JobsQueued
			# Show-ScriptStatus-JobMonitoring
			# Show-ScriptStatus-JobLoopTimeout
			# Show-ScriptStatus-RuntimeTotals

	#endregion Functions

	#region Job Tasks
	
	# DEBUG
	$ErrorActionPreference = "Inquire"
	
	# STOP AND REMOVE ANY RUNNING JOBS
	Stop-Job *
	Remove-Job * -Force
	
	Show-ScriptHeader -blanklines '4' -DashCount $DashCount -ScriptTitle $ScriptTitle
	
	# SHOULD SHOW ZERO JOBS RUNNING
	Get-JobCount
	Set-WinTitle-JobCount -WinTitle_Input $Global:WinTitle_Input -jobcount $Global:getjobcount.JobsRunning
	
	#region Job Loop
	
		[int]$hostcount = $HostList.Count
		$i = 0
		[boolean]$FirstGroup = $false
		Foreach ($ComputerName in $HostList) {
			$taskprogress = [int][Math]::Ceiling((($i / $hostcount) * 100))
			# Progress Bar
			Write-Progress -Activity "STARTING PATCHING ON - ($ComputerName)" -PercentComplete $taskprogress -Status "OVERALL PROGRESS - $taskprogress%"

			## THROTTLE RUNNING JOBS ##
			# Loop Until Less Than Max Jobs Running
			Get-JobCount
			Set-WinTitle-JobCount -WinTitle_Input $Global:WinTitle_Input -jobcount $Global:getjobcount.JobsRunning
			Remove-Jobs -JobLogFullName $JobLogFullName
			
			#region Throttle Jobs
			
				# PAUSE FOR A FEW AFTER THE FIRST 25 ARE QUEUED
				if (($Global:getjobcount.JobsRunning -ge '20') -and ($FirstGroup -eq $false)) {
					Sleep -Seconds 5
					[boolean]$FirstGroup = $true
				}
			
				While ($Global:getjobcount.JobCount -ge $MaxJobs) {
					Sleep -Seconds 5
					Remove-Jobs -JobLogFullName $JobLogFullName
					Get-JobCount
					Set-WinTitle-JobCount -WinTitle_Input $Global:WinTitle_Input -jobcount $Global:getjobcount.JobsRunning
				}
			
			#endregion Throttle Jobs
			
			#region Background Job
			
				Start-Job -RunAs32 -ScriptBlock {

					#region Job Variables
					
						$ComputerName = $Args[0]
						$SubScripts = $args[1]
						$Assets = $args[2]
						$ScriptVersion = $Args[3]
						$SkipVMToolsBool = $Args[4]
						$JobLogFullName = $args[5]
						$vCenter = $args[6]
						$MinFreeMB = $args[7]
						$SkipDiskSpaceCheckBool = $args[8]
						$UserDomain = $args[9]
						$UserName = $args[10]
						$ScriptHost = $args[11]
						$FileDateTime = $args[12]
						$SkipVMHardwareBool = $args[13]
						$LogPath = $args[14]
						$ResultsTextFullName = $args[15]
						$UseAltViCredsBool = $args[16]
						$ViCreds = $args[17]
						$SkipAllVmwareBool = $args[18]
						
						# DATE AND TIME
						$day = Get-Date -uformat "%m-%d-%Y"
						$JobStartTime = Get-Date -Format g
						$JobStartTimeF = Get-Date -Format g
						
						# NETWORK SHARES
						[string]$RemoteShareRoot = '\\' + $ComputerName + '\C$' 
						[string]$RemoteShare = Join-Path -Path $RemoteShareRoot -ChildPath 'WindowsPatching'
						
						# HISTORY LOG
						[string]$HistoryLogFileName = $ComputerName + '_InstallPatches_History.log' 
						[string]$LocalHistoryLogPath = Join-Path -Path $LogPath -ChildPath 'History' 
						[string]$RemoteHistoryLogPath = $RemoteShare 
						[string]$LocalHistoryLogFullName = Join-Path -Path $LocalHistoryLogPath -ChildPath $HistoryLogFileName
						[string]$RemoteHistoryLogFullName = Join-Path -Path $RemoteHistoryLogPath -ChildPath $HistoryLogFileName
						
						# LASTEST LOG
						[string]$LatestLogFileName = $ComputerName + '_InstallPatches_Latest.log' 
						[string]$LocalLatestLogPath = Join-Path -Path $LogPath -ChildPath 'Latest' 
						[string]$RemoteLatestLogPath = $RemoteShare 
						[string]$LocalLatestLogFullName = Join-Path -Path $LocalLatestLogPath -ChildPath $LatestLogFileName 
						[string]$RemoteLatestLogFullName = Join-Path -Path $RemoteLatestLogPath -ChildPath $LatestLogFileName
						
						# LAST PATCHES LOG
						[string]$LastPatchesLogFileName = $ComputerName + '_InstallPatches_Temp.log' 
						[string]$LocalLastPatchesLogPath = Join-Path -Path $LogPath -ChildPath 'Temp' 
						[string]$RemoteLastPatchesLogPath = $RemoteShare 
						[string]$LocalLastPatchesLogFullName = Join-Path -Path $LocalLastPatchesLogPath -ChildPath $LastPatchesLogFileName 
						[string]$RemoteLastPatchesLogFullName = Join-Path -Path $RemoteLastPatchesLogPath -ChildPath $LastPatchesLogFileName
						
						# TEMP WORK IN PROGRESS PATH
						[string]$WIPPath = Join-Path -Path $LogPath -ChildPath 'WIP' 
						[string]$WIPFullName = Join-Path -Path $WIPPath -ChildPath $ComputerName
						
						# SCRIPTS
						[string]$UpdateVBFileName = 'Install-Patches_1.0.3.vbs'
						[string]$RemoteUpdateVB = Join-Path -Path $RemoteShare -ChildPath $UpdateVBFileName
						[string]$LocalUpdateVB = Join-Path -Path $SubScripts -ChildPath $UpdateVBFileName
						[string]$UpdateVBRemoteCommand = 'cscript.exe C:\WindowsPatching\' + $UpdateVBFileName
											
						# SET INITIAL JOB SCOPE VARIBLES
						[boolean]$Failed = $false
						[boolean]$CompleteSuccess = $false
						[boolean]$Global:RebootFailed = $false
						[boolean]$PatchingSuccess = $false
						[boolean]$HardDiskCheckOK = $false
						[int]$Global:RebootCount = '0'
						[int]$InstalledPatchesCount = '0'
						$LogDataPatching = $null
						$LogDataVmHardware = $null
						$LogDataVmTools = $null
						$LogDataOutput = $null
						[Boolean]$ConnectSuccess = $true
					
					#endregion Job Variables
					
					#region Job Functions
					
						. "$SubScripts\Func_Get-Runtime_1.0.3.ps1"
						. "$SubScripts\Func_Get-DiskSpace_1.0.1.ps1"
						. "$SubScripts\Func_Get-PendingReboot_1.0.6.ps1"
						. "$SubScripts\Func_Get-VmHardware_1.0.5.ps1"
						. "$SubScripts\Func_Get-VmTools_1.0.9.ps1"
						. "$SubScripts\Func_Get-HostIP_1.0.5.ps1"
						. "$SubScripts\Func_Get-IPConfig_1.0.4.ps1"
						. "$SubScripts\Func_Get-OSVersion_1.0.9.ps1"
						. "$SubScripts\Func_Restart-Host_1.0.8.ps1"
						. "$SubScripts\Func_Send-VMPowerOff_1.0.4.ps1"
						. "$SubScripts\Func_Send-VMPowerOn_1.0.4.ps1"
						. "$SubScripts\Func_Update-VmHardware_1.0.6.ps1"
						. "$SubScripts\Func_Update-VmTools_1.0.8.ps1"
						. "$SubScripts\Func_Connect-ViHost_1.0.7.ps1"
						. "$SubScripts\Func_Disconnect-VIHost_1.0.1.ps1"
						. "$SubScripts\Func_Invoke-PSExec_1.0.7.ps1"
						. "$SubScripts\MultiFunc_Out-ScriptLog_1.0.3.ps1"
							# Out-ScriptLog-Header
							# Out-ScriptLog-Starttime
							# Out-ScriptLog-Error
							# Out-ScriptLog-JobTimeout
							# Out-ScriptLog-Footer	
					
					#endregion Job Functions
					
					#region Setup Files and Folders
						
						# REMOVE OLD FILES
						$filepaths = @(
							"\\$ComputerName\c$\WindowsPatching\SearchDownloadInstall-WUA.vbs",
							"\\$ComputerName\c$\WindowsPatching\SearchDownloadInstall-WUA_1.0.2.vbs",
							("\\$ComputerName\c$\WindowsPatching\" + $ComputerName + '_LastPatch.log'),
							"\\$ComputerName\c$\wuinstall.exe",
							"\\$ComputerName\c$\Update.vbs",
							("\\$ComputerName\c$\" +  $ComputerName + '_patchlog.txt')						
						)
						# Remove each item in the filepaths array if exists
						ForEach ($filepath in $filepaths) {
							if ((Test-Path -Path $filepath) -eq $true) {
								Remove-Item -Path $filepath -Force 
							}
						}
						
						$OldHistoryFileFullName = '\\' + $ComputerName + '\c$\WindowsPatching\' + $ComputerName + '_PatchHistory.log'
						if ((Test-Path -Path $OldHistoryFileFullName) -eq $true) {
							Rename-Item -Path $OldHistoryFileFullName -NewName $HistoryLogFileName -Force
						}
						
						# CREATE WIP TRACKING FILE IN WIP DIRECTORY
						if ((Test-Path -Path $WIPFullName) -eq $false) {
							New-Item -Item file -Path $WIPFullName -Force | Out-Null
						}
						
						# CREATE CLIENT PATCH DIRECTORY FOR SCRIPTS IF MISSING
						if ((test-path -Path $RemoteShare) -eq $False) {
							New-Item -Path $RemoteShareRoot -name WindowsPatching -ItemType directory -Force | Out-Null
						}
						
						#region Temp: Remove Old Remote Computer Directory
					
							if ((Test-Path -Path "$RemoteShareRoot\Windows-Patching") -eq $true) {
								if ((Test-Path -Path "$RemoteShareRoot\Windows-Patching\*.log") -eq $true) {
									Copy-Item -Path "$RemoteShareRoot\Windows-Patching\*.log" -Destination $RemoteShare -Force
								}
								Remove-Item -Path "$RemoteShareRoot\Windows-Patching" -Recurse -Force
							}
					
						#endregion Temp: Remove Old Remote Computer Directory

						# CREATE BLANK LastPatches AND HISTORY LOG ^Needed? (need for check complete pattern string check)
						if ((Test-Path -Path $RemoteHistoryLogFullName) -eq $false) {
							New-Item -Path $RemoteShare -Name $HistoryLogFileName -ItemType file -Force | Out-Null
						}
						if ((Test-Path -Path $LocalHistoryLogFullName) -eq $false) {
							New-Item -Path $LocalHistoryLogPath -Name $HistoryLogFileName -ItemType file -Force | Out-Null
						}
						
						# WRITE HISTORY LOG HEADER
						$DateTimeF = Get-Date -format g
						$LogData = $null
						$LogData = @(
							'',
							'',
							'',
							'******************************************************************************************',
							'******************************************************************************************',
							"JOB STARTED:     ($ComputerName) $DateTimeF",
							"SCRIPT VER:      $ScriptVersion",
							"ADMINUSER:       $UserDomain\$UserName",
							"SCRIPTHOST:       $ScriptHost"
						)
						$ScriptLogData = $LogData
						Add-Content -Path $LocalHistoryLogFullName,$RemoteHistoryLogFullName -Encoding ASCII -Value $LogData
						
					#endregion Setup Files and Folders

					#region Check Pending
					
						# CHECK FOR PENDING REBOOT
						Get-PendingReboot -ComputerName $ComputerName -SubScripts $SubScripts -Assets $Assets
								
						# WRITE OUTPUT OBJECT DATA TO HISTORY LOGS
						$results = $null
						$LogData = $null
						[array]$results = ($Global:GetPendingReboot | Format-List | Out-String).Trim('')
						$LogData = @(
							'',
							'CHECK FOR PENDING REBOOT',
							'-------------------------',
							"$results"
						)
						$ScriptLogData += $LogData
						Add-Content -Path $LocalHistoryLogFullName,$RemoteHistoryLogFullName -Encoding ASCII -Value $LogData

						[boolean]$reboot = $false
						# REBOOT IF CHECK PENDING FAILS
						if ($Global:GetPendingReboot.Success -eq $false) {
							[boolean]$reboot = $true
							$RebootReason = 'Check Pending Safe Measure'
						}
						# REBOOT IF PENDING
						if ($Global:GetPendingReboot.Pending -eq $true) {
							[boolean]$reboot = $true
							$RebootReason = 'Pending Reboot Check'
						}
						if ($reboot -eq $true) {
							# Update Logs
							$DateTimeF = Get-Date -format g
							$LogData = $null
							$LogData = @(
								'',
								"REBOOTING:       [$ComputerName] for $RebootReason ($DateTimeF)"
							)
							$ScriptLogData += $LogData
							Add-Content -Path $LocalHistoryLogFullName,$RemoteHistoryLogFullName -Encoding ASCII -Value $LogData
							
							Restart-Host -ComputerName $ComputerName -SubScripts $SubScripts
							$Global:RebootCount++
							$Global:rebootRuntimes += ' ' + $Global:RestartHost.RebootTime
							
							# WRITE OUTPUT OBJECT DATA TO HISTORY LOGS
							$results = $null
							$LogData = $null
							[array]$results = ($Global:RestartHost | Format-List | Out-String).Trim('')
							$LogData = @(
								'',
								'REBOOTING HOST',
								'--------------------------',
								"$results"
							)
							$ScriptLogData += $LogData
							Add-Content -Path $LocalHistoryLogFullName,$RemoteHistoryLogFullName -Encoding ASCII -Value $LogData
						}

					#endregion Check Pending
					
					#region Hard Drive Space Check
						
						## C: DRIVE SPACE CHECK ##
						if (($SkipDiskSpaceCheckBool -eq $false) -and ($Global:RebootFailed -eq $false)) {
							Get-DiskSpace -ComputerName $ComputerName -SubScripts $SubScripts -MinFreeMB $MinFreeMB
							# Write Results to Logs
							$results = $null
							$results = ($Global:GetDiskSpace | Format-List | Out-String).Trim('')
							$LogData = $null
							$LogData += @(
								'',
								'CHECK DRIVE SPACE',
								'------------------',
								"$results"
							)
							$ScriptLogData += $LogData
							Add-Content -Path $LocalHistoryLogFullName,$RemoteHistoryLogFullName -Encoding ASCII -Value $LogData
							
							if ($Global:GetDiskSpace.Passed -eq $true) {
									[boolean]$HardDiskCheckOK = $true
							}
							else
{
								[boolean]$Failed = $true
								[boolean]$HardDiskCheckOK = $false
							}
							[string]$FreeSpace = $Global:GetDiskSpace.FreeSpaceMB
							[string]$DriveSize = $Global:GetDiskSpace.DriveSize
							[boolean]$diskcheck = $Global:GetDiskSpace.Success
							[boolean]$DiskCheckPassed = $Global:GetDiskSpace.Passed
						}
						else
{
							# Selected not to check diskspace so setup var so script will continue.
							[boolean]$HardDiskCheckOK = $true
							[string]$FreeSpace = 'N/A'
							[string]$DriveSize = 'N/A'
							[string]$diskcheck = 'Skipped'
							[string]$DiskCheckPassed = 'N/A'
						}
						
					#endregion Hard Drive Space Check
					
					#region Patching
					
						if (($HardDiskCheckOK -eq $true) -and ($Global:RebootFailed -eq $false)) {								
														
						#region Windows Patching
						
							$DateTimeF = Get-Date -Format g
							# REMOVE LastPatches LOGS (So the script doesn't have a chance to pull old data)
							if ((Test-Path -Path $LocalLastPatchesLogFullName) -eq $true) {
								Remove-Item -Path $LocalLastPatchesLogFullName -Force | Out-Null
							}
							if ((Test-Path -Path $RemoteLastPatchesLogFullName) -eq $true) {
								Remove-Item -Path $RemoteLastPatchesLogFullName -Force | Out-Null
							}
							# IF Install-Patches.vbs MISSING THEN COPY TO CLIENT
							if ((Test-Path -Path $RemoteUpdateVB) -eq $False) {
								Copy-Item -Path $LocalUpdateVB -Destination $RemoteShare -Force | Out-Null 
							}
							
							# UPDATE HISTORY LOGS
							$DateTimeF = Get-Date -format g
							$LogData = $null
							$LogData = @(
								'',
								'',
								"WINDOWS PATCHING STARTED:     ($DateTimeF)",
								'******************************************************************************************'
							)
							$ScriptLogData += $LogData
							Add-Content -Path $LocalHistoryLogFullName,$RemoteHistoryLogFullName -Encoding ASCII -Value $LogData
							
							# REGISTER DLL FOR Install-Patches.vbs TO RUN ON CLIENT
							Invoke-PSExec -ComputerName $ComputerName -SubScripts $SubScripts -Assets $Assets -Timeout '300' -RemoteCommand 'regsvr32.exe /s scrrun.dll'
							# Write Results to Logs
							$results = $null
							$results = ($Global:InvokePSExec | Format-List | Out-String).Trim('')
							$LogDataPatching += @(
								'',
								'REGISTER DLL FOR VBS SCRIPT ON REMOTE',
								'-------------------------------------',
								"$results"
							)
						
#							if ($Global:InvokePSExec.Success -eq $true) {
#								[boolean]$runscrrunsuccess = $true # ^Not used yet
#							}
#							else
{
#								[boolean]$Failed = $true
#								[boolean]$runscrrunsuccess = $false # ^Not used yet
#							}
#							
							# PATCH AND REBOOT UNTIL NO PATCHES NEEDED OR FAILURE
							[int]$patchrounds = 0
							Do {
								$patchrounds++
								[boolean]$RemoteLastPatchesLogfound = $false
								[boolean]$PatchingSuccess = $false
								# REMOVE ANY EXISTING LastPatchesLOG ON ADMIN HOST AND CLIENT
								if ((Test-Path -Path $LocalLastPatchesLogFullName) -eq $true) {
									Remove-Item -Path $LocalLastPatchesLogFullName -Force | Out-Null
								}
								if ((Test-Path -Path $RemoteLastPatchesLogFullName) -eq $true) {
									Remove-Item -Path $RemoteLastPatchesLogFullName -Force | Out-Null
								}
								
								#region Check Pending
									
									if ($patchrounds -gt '1') {
										# CHECK FOR PENDING REBOOT
										Get-PendingReboot -ComputerName $ComputerName -SubScripts $SubScripts -Assets $Assets
								
										# WRITE OUTPUT OBJECT DATA TO HISTORY LOGS
										$results = $null
										[array]$results = ($Global:GetPendingReboot | Format-List | Out-String).Trim('')
										$LogDataPatching += @(
											'',
											'CHECK FOR PENDING REBOOT',
											'-------------------------',
											"$results"
										)

										[boolean]$reboot = $false
										# REBOOT IF CHECK PENDING FAILS
										if ($Global:GetPendingReboot.Success -eq $false) {
											[boolean]$reboot = $true
											$RebootReason = 'Check Pending Safe Measure'
										}
										# REBOOT IF PENDING
										if ($Global:GetPendingReboot.Pending -eq $true) {
											[boolean]$reboot = $true
											$RebootReason = 'Pending Reboot Check'
										}
										if ($reboot -eq $true) {
											# Update Logs
											$DateTimeF = Get-Date -format g
											$LogDataPatching += @(
												'',
												"REBOOTING:       [$ComputerName] for $RebootReason ($DateTimeF)"
											)
											
											Restart-Host -ComputerName $ComputerName -SubScripts $SubScripts
											$Global:RebootCount++
											$Global:rebootRuntimes += ' ' + $Global:RestartHost.RebootTime
											
											# WRITE OUTPUT OBJECT DATA TO HISTORY LOGS
											$results = $null
											[array]$results = ($Global:RestartHost | Format-List | Out-String).Trim('')
											$LogDataPatching += @(
												'',
												'REBOOTING HOST',
												'--------------------------',
												"$results"
											)
										}
									}
								
								#endregion Check Pending

								# Update Logs
								$DateTimeF = Get-Date -format g
								$LogDataPatching += @(
									'',
									"PATCHING:        [ROUND $patchrounds] ($DateTimeF)"
								)
								
								# RUN Install-Patches.vbs ON CLIENT
								Invoke-PSExec -ComputerName $ComputerName -SubScripts $SubScripts -Assets $Assets -Timeout '5400' -RemoteCommand $UpdateVBRemoteCommand
								
								# Write Results to Logs
								$results = $null
								$results = ($Global:InvokePSExec | Format-List | Out-String).Trim('')
								$LogDataPatching += @(
									'',
									'RUN WUAVBS SCRIPT ON REMOTE',
									'---------------------------',
									"$results"
								)
								
								# REBOOT IF RUN PSEXEC NOT SUCCESSFUL AND TRY AGAIN
								if ($Global:InvokePSExec.Success -eq $false) {
									# Update Logs
									$DateTimeF = Get-Date -format g
									$LogDataPatching += @(
										'',
										"REBOOTING:       [$ComputerName] for WU VBS SCRIPT FAILED ($DateTimeF)"
									)
									
									Restart-Host -ComputerName $ComputerName -SubScripts $SubScripts
									$Global:RebootCount++
									$Global:rebootRuntimes += ' ' + $Global:RestartHost.RebootTime
									
									# WRITE RESULTS TO HISTORY LOGS LOGARRAY
									$results = $null
									$LogData = $null
									[array]$results = ($Global:RestartHost | Format-List | Out-String).Trim('')
									$LogDataPatching += @(
										'',
										'REBOOTING HOST',
										'---------------',
										"$results"
									)
									# RUN Install-Patches.vbs ON CLIENT
									# Update Logs
									$DateTimeF = Get-Date -format g
									$LogDataPatching += @(
										'',
										"WUAVBS:          [RUN] Retry after Reboot ($DateTimeF)"
									)

									Invoke-PSExec -ComputerName $ComputerName -SubScripts $SubScripts -Assets $Assets -Timeout '5400' -RemoteCommand $UpdateVBRemoteCommand
									# Write Results to Logs
									$results = $null
									$results = ($Global:InvokePSExec | Format-List | Out-String).Trim('')
									$LogDataPatching += @(
										'',
										'RUN WUAVBS SCRIPT ON REMOTE',
										'---------------------------',
										"$results"
									)
								}
								# SET FOR OUTPUT FILE
								$WuVBSExitCode = $Global:InvokePSExec.ExitCode
								$WuVBSExitCodedesc = $Global:InvokePSExec.ExitCodeDesc | Out-String
								
								if ($Global:InvokePSExec.Success -eq $true) {
									[boolean]$RunVBSSuccess = $true
								}
								else
{
									[boolean]$Failed = $true
									[boolean]$RunVBSSuccess = $false
								}
								
								# EXIT WINDOWS PATCHING IF WUAVBS SCRIPT FAILED
								if ($RunVBSSuccess -eq $true) {
								
									# Test that the Client LastPatches Log Exists and then Copy to Admin Host for up to 2.5 minutes
									[int]$copylogloop = 0
									
									# Update Logs
									$DateTimeF = Get-Date -format g
									$LogDataPatching += @(
										'',
										"PATCHING:        [COPYLOG] Loop Started ($DateTimeF)"
									)

									Do {
										$copylogloop++
										[boolean]$RemoteLastPatchesLogfound = $false
										[boolean]$ComputerNamelogcopyerror = $true
										[boolean]$LocalLastPatchesLogfound = $false
										Try {
											# Update Logs
											$DateTimeF = Get-Date -format g
											$LogDataPatching += @(
												'',
												"PATCHING:        [COPYLOG] Test Path to Client LastPatches Log ($DateTimeF)"
											)

											[boolean]$RemoteLastPatchesLogfound = Test-Path -Path $RemoteLastPatchesLogFullName -ErrorAction Stop
										}
										Catch {
											[boolean]$RemoteLastPatchesLogfound = $false
										}
										if ($RemoteLastPatchesLogfound -eq $true) {
											Try {
												# Update Logs
												$DateTimeF = Get-Date -format g
												$LogDataPatching += @(
													'',
													"PATCHING:        [COPYLOG] Copy Client LastPatches Log to Script Host ($DateTimeF)"
												)

												# COPY AND REPLACE Local LastPatches LOG WITH CLIENT LastPatches LOG
												Copy-Item -Path $RemoteLastPatchesLogFullName -Destination $LocalLastPatchesLogPath -Force | Out-Null -ErrorAction Stop
												[boolean]$ComputerNamelogcopyerror = $false
											}
											Catch {
												[boolean]$ComputerNamelogcopyerror = $true
											}
											if ($ComputerNamelogcopyerror -eq $false) {
												# TEST IF FILE IS ON Script HOST
												Try {
													# Update Logs
													$DateTimeF = Get-Date -format g
													$LogDataPatching += @(
														'',
														"PATCHING:        [COPYLOG] Test Path to Local LastPatches Log ($DateTimeF)"
													)
													
													$LocalLastPatchesLogfound = Test-Path -Path $LocalLastPatchesLogFullName -ErrorAction Stop
												}
												Catch {
													[boolean]$LocalLastPatchesLogfound = $false
												}
											}
											else
{
												Sleep -Seconds 1
											}
										}
										else
{
											Sleep -Seconds 1
										}
									}
									Until (($LocalLastPatchesLogfound -eq $true) -or ($copylogloop -ge 900))
									
									# Update Logs
									$DateTimeF = Get-Date -format g
									$LogDataPatching += @(
										'',
										"PATCHING:        [COPYLOG] Loop Ended ($DateTimeF)",
										'',
										"PATCHING:        [COPYLOG] Copy Log Loop Count: $copylogloop ($DateTimeF)"
									)
									
									# If admin LastPatches log found then update logs and reboot as needed
									if ($LocalLastPatchesLogfound -eq $true) {
										# Update Logs
										$DateTimeF = Get-Date -format g
										$LogDataPatching += @(
											'',
											"PATCHING:        [CHECKLOG] Found Local LastPatches Log ($DateTimeF)"
										)
										
										[array]$patchlogdata = Get-Content -Path $LocalLastPatchesLogFullName
										[int]$loglinecount = $patchlogdata.Count
										if ($patchlogdata) {
											# Update Logs
											$DateTimeF = Get-Date -format g
											$results = $null
											$results = $patchlogdata | Out-String
											$LogDataPatching += @(
												'',
												"LAST PATCHES LOG DATA ($DateTimeF)",
												'**************************************************************',
												'',
												"$results",
												'',
												'**************************************************************'
											)
										}
										
										# Update Logs
										$DateTimeF = Get-Date -format g
										$LogDataPatching += @(
											'',
											"PATCHING:        [CHECKLOG] Local LastPatches Log Line Count = $loglinecount ($DateTimeF)"
										)

										if ($loglinecount -le 1) {
											[boolean]$LastPatchesLogEmpty = $true

											# Update Logs
											$DateTimeF = Get-Date -format g
											$LogDataPatching += @(
												'',
												"PATCHING:        [CHECKLOG] ERROR: Local LastPatches Log is Empty ($DateTimeF)"
											)
										}
										else
{
											[boolean]$LastPatchesLogEmpty = $false
											
											# Update Logs
											$DateTimeF = Get-Date -format g
											$LogDataPatching += @(
												'',
												"PATCHING:        [CHECKLOG] Local LastPatches Log is not Empty ($DateTimeF)"
											)
										}
										# Get Applied Patches Count
										[array]$patches = $patchlogdata | Where-Object {$_ -like "*>*"}
										[int]$InstalledPatchesCount += $patches.Count
										
										# REBOOT IF NEEDED
										if ($LastPatchesLogEmpty -eq $false) {
											# Read admin LastPatches log file to see if a reboot is required 
											# Using the -Quiet switch makes the cmdlet return a True of False if it finds the string
											$rebootneeded = Select-String -Pattern 'Reboot Required: True' -Path $LocalLastPatchesLogFullName -Quiet
											
											# Reboot if Admin LastPatches Log has "Reboot Required: True"
											if ($rebootneeded -eq $true) {
												# Update Logs
												$DateTimeF = Get-Date -format g
												$LogDataPatching += @(
													'',
													"REBOOTING:       [$ComputerName] for Windows Patching Required Reboot ($DateTimeF)"
												)
												
												Restart-Host -ComputerName $ComputerName -SubScripts $SubScripts
												$Global:RebootCount++
												$Global:rebootRuntimes += ' ' + $Global:RestartHost.RebootTime
												
												# WRITE OUTPUT OBJECT DATA TO HISTORY LOGS
												$results = $null
												$LogData = $null
												[array]$results = ($Global:RestartHost | Format-List | Out-String).Trim('')
												$LogDataPatching += @(
													'',
													'REBOOTING HOST',
													'--------------------------',
													"$results"
												)
											}
											else
{
												# Update Logs
												$DateTimeF = Get-Date -format g
												$LogDataPatching += @(
													'',
													"PATCHING:        [CHECK PENDING] Reboot not required ($DateTimeF)"
												)
											}
										}
										else
{
											[boolean]$Failed = $true
										}
										
										# DETERMINE IF MORE UPDATES ARE NEEDED
										## Quiet switch gives a True or False result
										[boolean]$PatchingSuccess = Select-String -Pattern 'No updates to install.' -Path $LocalLastPatchesLogFullName -Quiet
										
									} # LastPatches Log Copied to Admin Host
									Elseif ($copylogloop -ge 900) {
										[boolean]$Failed = $true
										[boolean]$RemoteLastPatchesLogfound = $false
#										[string]$currentvariables = Get-Variable | Out-String
#										Out-ScriptLog-Error -ComputerName $ComputerName -ScriptLogFullName $ScriptLogFullName -errortitle 'PATH-TEST TO CLIENT LastPatches LOG FAILED: CurrentVariables' -Notes $currentvariables
#										[string]$errorlog = $Error | Out-String
#										Out-ScriptLog-Error -ComputerName $ComputerName -ScriptLogFullName $ScriptLogFullName -errortitle 'PATH-TEST TO CLIENT LastPatches LOG FAILED: ErrorLog' -Notes $errorlog
										
										# Update Logs
										$DateTimeF = Get-Date -format g
										$LogDataPatching += @(
											'',
											"PATCHING:        [ERROR] PATCH LOG MISSING ($DateTimeF)"
										)
									}
								} # IF WUAVBS Success
							} 	
							# DO Windows Patching Loop Until: It has Looped 4 Times OR The Admin LastPatches Log has "No Updates to Install" string OR Reboot Failed OR Client LastPatches Patch Log not found OR Client LastPatches Patch Log is empty
							Until (($PatchingSuccess -eq $true) -or ($patchrounds -ge 8) -or ($Global:RebootFailed -eq $true) -or ($RemoteLastPatchesLogfound -eq $false)-or ($LastPatchesLogEmpty -eq $true) -or ($RunVBSSuccess -eq $false))
							
							# DETERMINE WHAT CONDITION CAUSED LOOP TO EXIT
							## The order matters because of false positives if bails
							if ($PatchingSuccess -eq $true) {
								$patchloopexitreason = 'No updates to install'
							}
							Elseif ($RunVBSSuccess -eq $false) {
								$patchloopexitreason = 'Windows Update VBS Script Failed'
								[boolean]$Failed = $true
							}
							Elseif ($patchrounds -ge 8) {
								$patchloopexitreason = 'Over Patching Round Limit (8)'
								[boolean]$Failed = $true
							}
							Elseif ($Global:RebootFailed -eq $true) {
								$patchloopexitreason = 'Reboot Failed'
								[boolean]$Failed = $true
							}
							Elseif ($RemoteLastPatchesLogfound -eq $false) {
								$patchloopexitreason = 'Remote LastPatches Log Not Found'
								[boolean]$Failed = $true
							}
							Elseif ($LastPatchesLogEmpty -eq $true) {
								$patchloopexitreason = 'Remote LastPatches Log is Empty'
								[boolean]$Failed = $true
							}

							# Update Log
							$DateTimeF = Get-Date -format g
							$LogDataPatching += @(
								'',
								"PATCHING:        [PATCH LOOP] EXIT REASON: $patchloopexitreason ($DateTimeF)"
							)
							$ScriptLogData += $LogDataPatching
							# Update History Log for Patching Section
							Add-Content -Path $LocalHistoryLogFullName,$RemoteHistoryLogFullName -Encoding ASCII -Value $LogDataPatching
							
						#endregion Windows Patching

						#region Vmtools
														
							# If Patching was successful AND Vmtools Upgrade Selected AND No Reboot Failures: Then Start Vmtools check/upgrade
							if (($PatchingSuccess -eq $true) -and ($SkipVMToolsBool -eq $false) -and ($Global:RebootFailed -ne $true) -and ($SkipAllVmwareBool -eq $false)) {
								# UPDATE HISTORY LOGS
								$DateTimeF = Get-Date -format g
								$LogData = $null
								$LogData = @(
									'',
									'',
									"VMTOOLS CHECK-UPGRADE STARTED:     ($DateTimeF)",
									'******************************************************************************************'
								)
								$ScriptLogData += $LogData
								Add-Content -Path $LocalHistoryLogFullName,$RemoteHistoryLogFullName -Encoding ASCII -Value $LogData
								
								Get-VmTools -ComputerName $ComputerName -SubScripts $SubScripts -vCenter $vCenter -UseAltViCredsBool $UseAltViCredsBool -ViCreds $ViCreds -StayConnected 
								$VmToolsOK = $Global:GetVmTools.VmToolsOK
								
								# Write Results to Logs
								$results = $null
								$results = ($Global:GetVmTools | Format-List | Out-String).Trim('')
								$results2 = $null 
								$results2 = ($Global:ConnectVIHost | Format-List | Out-String).Trim('')
								$LogDataVmTools += @(
									'',
									'CHECK VMTOOLS 1',
									'----------------',
									"$results",
									'',
									'CONNECT TO VISERVER',
									'--------------------',
									"$results2"
								)
								
								if ($Global:GetVmTools.Success -eq $true) {
									# IF VMTOOLS ARE OLD VERSION THEN PULL IPCONFIG
									if (($Global:GetVmTools.VmtoolsOK -eq $false) -and ($Global:GetVmTools.VmFound -eq $true) -and ($Global:GetVmTools.WindowsGuest -eq $true)) {
										Get-IPConfig -ComputerName $ComputerName -SubScripts $SubScripts
										# Write Results to Logs
										$results = $null
										$results = ($Global:GetIPConfig | Format-List | Out-String).Trim('')
										$results2 = $null 
										$results2 = ($Global:GetIPConfig.IPConfig | Format-List | Out-String).Trim('')
										$LogDataVmTools += @(
											'',
											'GET IPCONFIG',
											'-------------',
											"$results",
											'',
											"$results2"
										)
										
										# IF IPCONFIG PULLED UPGRADE VMTOOLS
										if ($Global:GetIPConfig.Success -eq $true) {
											[boolean]$IPConfigSuccess = $true
#											[boolean]$VmTUpdateTriggered = $true
											Update-VmTools -ComputerName $ComputerName -SubScripts $SubScripts -vCenter $vCenter -UseAltViCredsBool $UseAltViCredsBool -ViCreds $ViCreds -StayConnected
											
											# Write Results to Logs
											$results = $null
											$results = ($Global:UpdateVmTools | Format-List | Out-String).Trim('')
											$results2 = $null 
											$results2 = ($Global:ConnectVIHost | Format-List | Out-String).Trim('')
											$LogDataVmTools += @(
												'',
												'UPGRADE VMTOOLS',
												'----------------',
												"$results",
												'',
												'CONNECT TO VISERVER',
												'--------------------',
												"$results2"
											)
											
											# IF SUCCESSFUL REBOOT
											if ($Global:UpdateVmTools.Success -eq $true) {
												[boolean]$VmTUpdateSuccess = $true
												# Update Logs
												$DateTimeF = Get-Date -format g
												$LogDataVmTools += @(
													'',
													"REBOOTING:       [$ComputerName] for Vmtools upgraded ($DateTimeF)"
												)
												
												Restart-Host -ComputerName $ComputerName -SubScripts $SubScripts
												$Global:RebootCount++
												$Global:rebootRuntimes += ' ' + $Global:RestartHost.RebootTime
												
												# WRITE OUTPUT OBJECT DATA TO HISTORY LOGS
												$results = $null
												$LogData = $null
												[array]$results = ($Global:RestartHost | Format-List | Out-String).Trim('')
												$LogDataVmTools += @(
													'',
													'REBOOTING HOST',
													'---------------',
													"$results"
												)
												
												Get-VmTools -ComputerName $ComputerName -SubScripts $SubScripts -vCenter $vCenter -UseAltViCredsBool $UseAltViCredsBool -ViCreds $ViCreds -StayConnected 
												$VmToolsOK = $Global:GetVmTools.VmToolsOK
												
												# Write Results to Logs
												$results = $null
												$results = ($Global:GetVmTools | Format-List | Out-String).Trim('')
												$results2 = $null 
												$results2 = ($Global:ConnectVIHost | Format-List | Out-String).Trim('')
												$LogDataVmTools += @(
													'',
													'CHECK VMTOOLS 2',
													'----------------',
													"$results",
													'',
													'CONNECT TO VISERVER',
													'--------------------',
													"$results2"
												)
												if ($Global:GetVmTools.VmtoolsOK -eq $true) {
													[Boolean]$VmTUpdateSuccess = $true
												}
											}
											# IF FAILED UPDATE
											Elseif ($Global:UpdateVmTools.Success -eq $false) {
												[boolean]$Failed = $true
												[boolean]$VmTUpdateSuccess = $false
											}
											# ELSE OTHER FAILURE
											else
{
												[boolean]$Failed = $true
												[boolean]$VmTUpdateSuccess = $false
											}
										} #/IF ipconfig pulled then upgrade
										else
{
											[boolean]$Failed = $true
											[boolean]$IPConfigSuccess = $false
											[boolean]$VmTUpdateSuccess = $false
										}
									} #/If vmtools old, vm found and Windows Guest then upgrade
								}
								else
{
									[boolean]$Failed = $true
								}
								# DISCONNECT FROM vCenter SERVER
								if ($SkipVMHardwareBool -eq $true) {
									Disconnect-VIHost
									
									# Write Results to Logs
									$results = $null
									$results = ($Global:DisconnectVIHost | Format-List | Out-String).Trim('')
									$LogDataVmTools += @(
										'',
										'DISCONNECT FROM VISERVER',
										'------------------------',
										"$results"
									)
								}
								# Update History Log for VmTools Section
								$ScriptLogData += $LogDataVmTools
								Add-Content -Path $LocalHistoryLogFullName,$RemoteHistoryLogFullName -Encoding ASCII -Value $LogDataVmTools
							} #/If Vmtools check-upgrade selected at prompt
								
						#endregion Vmtools

						#region Vmharware
										
							## If Patching was successful AND Vmtools Hardware Upgrade Selected AND VM was found AND No Reboot Failures: Then Start VM Hardware check/upgrade
							if (($PatchingSuccess -eq $true) -and ($SkipVMHardwareBool -eq $false) -and ($Global:GetVmTools.VmFound -eq $true) -and ($Global:RebootFailed -ne $true) -and ($SkipAllVmwareBool -eq $false)) {
								# UPDATE HISTORY LOGS
								$DateTimeF = Get-Date -format g
								$LogData = $null
								$LogData = @(
									'',
									'',
									"VMHARDWARE CHECK-UPGRADE STARTED:     ($DateTimeF)",
									'******************************************************************************************'
								)
								$ScriptLogData += $LogData
								Add-Content -Path $LocalHistoryLogFullName,$RemoteHistoryLogFullName -Encoding ASCII -Value $LogData
							
								Get-VmHardware -ComputerName $ComputerName -SubScripts $SubScripts -vCenter $vCenter -UseAltViCredsBool $UseAltViCredsBool -ViCreds $ViCreds -StayConnected
								$VmHardwareOK = $Global:GetVmHardware.VmHardwareOK
								# Write Results to Logs
								$results = $null
								$results = ($Global:GetVmHardware | Format-List | Out-String).Trim('')
								$LogDataVmHardware += @(
									'',
									'CHECK VMHARDWARE 1',
									'------------------',
									"$results"
								)
								
								# IF Check Successful Proceed with evaluation conditions
								if ($Global:GetVmHardware.Success -eq $true) {
									
									# If VMHardware version is not current then upgrade
									if ($Global:GetVmHardware.VmHardwareOK -eq $false) {
										# CHECK TOOLS ARE UP-TO-DATE
										Get-VmTools -ComputerName $ComputerName -SubScripts $SubScripts -vCenter $vCenter -UseAltViCredsBool $UseAltViCredsBool -ViCreds $ViCreds -StayConnected 
										$VmToolsOK = $Global:GetVmTools.VmToolsOK
										
										# Write Results to Logs
										$results = $null
										$results = ($Global:GetVmTools | Format-List | Out-String).Trim('')
										$results2 = $null 
										$results2 = ($Global:ConnectVIHost | Format-List | Out-String).Trim('')
										$LogDataVmTools += @(
											'',
											'CHECK VMTOOLS 3',
											'----------------',
											"$results",
											'',
											'CONNECT TO VISERVER',
											'--------------------',
											"$results2"
										)
										# If Vmware Tools are up-to-date then upgrade Vmware hardware version
										if ($Global:GetVmTools.VmtoolsOK -eq $true) {
										
											# IF IPCONFIG NOT LOGGED FROM VMTOOLS SECTION THEN LOG IT
											if ($Global:GetIPConfig.Success -ne $true) {
												Get-IPConfig -ComputerName $ComputerName -SubScripts $SubScripts
												# Write Results to Logs
												$results = $null
												$results = ($Global:GetIPConfig | Format-List | Out-String).Trim('')
												$results2 = $null
												$results2 = ($Global:GetIPConfig.IPConfig | Format-List | Out-String).Trim('')
												$LogDataVmHardware += @(
													'',
													'GET IPCONFIG',
													'-------------',
													"$results",
													'',
													"$results2"
												)
											}
											
											# IF IPCONFIG LOGGED UPGRADE VM HARDWARE
											if ($Global:GetIPConfig.Success -eq $true) {
												$DateTimeF = Get-Date -format g
												$LogDataVmHardware += @(
													'',
													"VMHAREWARE:      [UPGRADING] ($DateTimeF)",
													"VMHAREWARE:      [SHUTDOWN TRIGGERED] ($DateTimeF)"
												)
												Send-VMPowerOff -ComputerName $ComputerName -SubScripts $SubScripts -vCenter $vCenter -UseAltViCredsBool $UseAltViCredsBool -ViCreds $ViCreds -StayConnected
												
												# Write Results to Logs
												$results = $null
												$results = ($Global:SendVMPowerOff | Format-List | Out-String).Trim('')
												$LogDataVmHardware += @(
													'',
													'TURN OFF VM',
													'------------',
													"$results"
												)
												
												if ($Global:SendVMPowerOff.VmTurnedOff -eq $true) {
													# Update Logs
													$DateTimeF = Get-Date -format g
													$LogDataVmHardware += @(
														'',
														"VMHAREWARE:      [UPGRADE TRIGGERED] ($DateTimeF)"
													)

#													[boolean]$VmHUpdateTriggered = $true
													# Trigger VMHardware Upgrade
													Update-VmHardware -ComputerName $ComputerName -SubScripts $SubScripts -vCenter $vCenter -UseAltViCredsBool $UseAltViCredsBool -ViCreds $ViCreds -Version $GetVmHardware.VmHostLatest -StayConnected
													
													# Write Results to Logs
													$results = $null
													$results = ($Global:UpdateVmHardware | Format-List | Out-String).Trim('')
													$LogDataVmHardware += @(
														'',
														'UPGRADE VMHARDWARE',
														'------------------',
														"$results"
													)
													
													if ($Global:UpdateVmHardware.Success -eq $true) {
														# Update Logs
														$DateTimeF = Get-Date -format g
														$LogDataVmHardware += @(
															'',
															"VMHAREWARE:      [POWERON TRIGGERED] ($DateTimeF)"
														)
														Send-VMPowerOn -ComputerName $ComputerName -SubScripts $SubScripts -vCenter $vCenter -UseAltViCredsBool $UseAltViCredsBool -ViCreds $ViCreds -StayConnected
														
														# Write Results to Logs
														$results = $null
														$results = ($Global:SendVMPowerOn | Format-List | Out-String).Trim('')
														$LogDataVmHardware += @(
															'',
															'TURN ON VM',
															'-----------',
															"$results"
														)
														
														# UPGRADE VERIFICATION
														Get-VmHardware -ComputerName $ComputerName -SubScripts $SubScripts -vCenter $vCenter -UseAltViCredsBool $UseAltViCredsBool -ViCreds $ViCreds -StayConnected
														$VmHardwareOK = $Global:GetVmHardware.VmHardwareOK
														# Write Results to Logs
														$results = $null
														$results = ($Global:GetVmHardware | Format-List | Out-String).Trim('')
														$LogDataVmHardware += @(
															'',
															'CHECK VMHARDWARE 2',
															'------------------',
															"$results"
														)
														
														if ($Global:GetVmHardware.VmHardwareOK -eq $true) {
															[boolean]$VmHUpdateSuccess = $true
															# Update Logs
															$DateTimeF = Get-Date -format g
															$LogDataVmHardware += @(
																'',
																"VMHAREWARE:      [VMHARDWARE VERSION $vmhver] ($DateTimeF)",
																"VMHAREWARE:      [UPGRADED] ($DateTimeF)"
															)
														}
														else
{
															[boolean]$Failed = $true
															[boolean]$VmHUpdateSuccess = $false
															# Update Logs
															$DateTimeF = Get-Date -format g
															$LogDataVmHardware += @(
																'',
																"VMHAREWARE:      [ERROR] VM HARDWARE UPGRADE FAILED ($DateTimeF)"
															)
														}
													} #/If VM Hardware Upgrade Successful
												} #/If VM Turned Off
											} #/If IP Logged
											else
{
												[boolean]$Failed = $true
												[boolean]$VmHUpdateSuccess = $false
												[boolean]$IPConfigSuccess = $false
												# Update Logs
												$DateTimeF = Get-Date -format g
												$LogDataVmHardware += @(
													'',
													"VMHAREWARE:      [ERROR] IP CONFIGURATION WAS NOT LOGGED FOR VMHARDWARE UPGRADE ($DateTimeF)"
												)
											}
										} #/If Vmtools OK
										else
{
											[boolean]$Failed = $true
											[boolean]$VmHUpdateSuccess = $false
											# Update Logs
											$DateTimeF = Get-Date -format g
											$LogDataVmHardware += @(
												'',
												"VMHAREWARE:      [ERROR] VMTOOLS STATUS NOT OK. VM HARDWARE UPGRADE CANCELLED ($DateTimeF)"
											)
										}
									} #/If VmHardwareOK is false
								} #/If VMHardware Check Successful
								else
{
									[boolean]$Failed = $true
									[boolean]$VmHUpdateSuccess = $false
									# Update Logs
									$DateTimeF = Get-Date -format g
									$LogDataVmHardware += @(
										'',
										"VMHAREWARE:      [ERROR] VM HARDWARE CHECK RESULTS FAILED ($DateTimeF)"
									)
								}
								# DISCONNECT FROM vCenter SERVER
								Disconnect-VIHost
								
								# Write Results to Logs
								$results = $null
								$results = ($Global:DisconnectVIHost | Format-List | Out-String).Trim('')
								$LogDataVmHardware += @(
									'',
									'DISCONNECT FROM VISERVER',
									'------------------------',
									"$results"
								)
								
								# Update History Log for VmTools Section
								$ScriptLogData += $LogDataVmHardware
								Add-Content -Path $LocalHistoryLogFullName,$RemoteHistoryLogFullName -Encoding ASCII -Value $LogDataVmHardware
								
							} #/If Check VM Hardware selected at prompt and reboot has not failed
							
							
						#endregion Vmhardware
						
						#region Check Pending
						
							if (($PatchingSuccess -eq $true) -and ($Global:RebootFailed -ne $true)) {
								# CHECK FOR PENDING REBOOT
								Get-PendingReboot -ComputerName $ComputerName -SubScripts $SubScripts -Assets $Assets
								
								# WRITE OUTPUT OBJECT DATA TO HISTORY LOGS
								$results = $null
								$LogData = $null
								[array]$results = ($Global:GetPendingReboot | Format-List | Out-String).Trim('')
								$LogData = @(
									'',
									'CHECK FOR PENDING REBOOT',
									'-------------------------',
									"$results"
								)
								$ScriptLogData += $LogData
								Add-Content -Path $LocalHistoryLogFullName,$RemoteHistoryLogFullName -Encoding ASCII -Value $LogData

								[boolean]$reboot = $false
								# REBOOT IF CHECK PENDING FAILS
								if ($Global:GetPendingReboot.Success -eq $false) {
									[boolean]$reboot = $true
									$RebootReason = 'Check Pending Safe Measure'
								}
								# REBOOT IF PENDING
								if ($Global:GetPendingReboot.Pending -eq $true) {
									[boolean]$reboot = $true
									$RebootReason = 'Pending Reboot Check'
								}
								if ($reboot -eq $true) {
									# Update Logs
									$DateTimeF = Get-Date -format g
									$LogData = $null
									$LogData = @(
										'',
										"REBOOTING:       [$ComputerName] for $RebootReason ($DateTimeF)"
									)
									$ScriptLogData += $LogData
									Add-Content -Path $LocalHistoryLogFullName,$RemoteHistoryLogFullName -Encoding ASCII -Value $LogData
									
									Restart-Host -ComputerName $ComputerName -SubScripts $SubScripts
									$Global:RebootCount++
									$Global:rebootRuntimes += ' ' + $Global:RestartHost.RebootTime
									
									# WRITE OUTPUT OBJECT DATA TO HISTORY LOGS
									$results = $null
									$LogData = $null
									[array]$results = ($Global:RestartHost | Format-List | Out-String).Trim('')
									$LogData = @(
										'',
										'REBOOTING HOST',
										'--------------------------',
										"$results"
									)
									$ScriptLogData += $LogData
									Add-Content -Path $LocalHistoryLogFullName,$RemoteHistoryLogFullName -Encoding ASCII -Value $LogData
								}
							}
										
						#endregion Check Pending
							
						} # If Diskspace OK and reboot didn't fail, Else Bailout but finish Output Report
					
					#endregion Patching
					
					#region Cleanup WIP File
					
						
						# REMOVE WIP OBJECT FILE
						if ((Test-Path -Path $WIPFullName) -eq $true) {
							Remove-Item -Path $WIPFullName -Force
						}
					
					#endregion Cleanup WIP File
					
					#region Generate Report
					
						# UPDATE HISTORY LOGS
						$DateTimeF = Get-Date -format g
						$LogData = $null
						$LogData = @(
							'',
							'',
							"GENERATING REPORT:     ($DateTimeF)",
							'******************************************************************************************'
						)
						$ScriptLogData += $LogData
						Add-Content -Path $LocalHistoryLogFullName,$RemoteHistoryLogFullName -Encoding ASCII -Value $LogData
						
						# Get VmTools, VmHardware and VmHost Versions for Output
						if (($SkipVMToolsBool -eq $false) -and ($SkipAllVmwareBool -eq $false)) {
							if ($Global:GetVmTools.VmFound -eq $true) {
								[string]$VmToolsVersion = $Global:GetVmTools.GuestToolsVersion
								[string]$OSVersion = $Global:GetVmTools.OSVersion
								[string]$HostIP = $Global:GetVmTools.VMIP
								[string]$VmDataStores = 'Error'
								[string]$VmDataStores = $Global:GetVmTools.VmDatastores
								# If more than one DataStore is assigned $vmdatastores will be an array and this flatten and formats it for the output.
								$vmd = $null
								Foreach ($vmd in $VmDataStores) {
									$VmDataStore += $vmd + ' ' 
								}
							}
						}
						# If not a VM or VM checks not ran, then pull OS and IP in Alternate way
						else
{
							Get-OSVersion -ComputerName $ComputerName -SubScripts $SubScripts -SkipVimQuery
							if ($Global:GetOSVersion.Success -eq $true) {
								[string]$OSArch = $Global:GetOSVersion.OSArch
								[string]$OSVersion = $Global:GetOSVersion.OSVersion
							}
							else
{
								[string]$OSArch = 'Error'
								[string]$OSVersion = 'Error'
							}
							# Get Client IP Address
							Get-HostIP -ComputerName $ComputerName -SubScripts $SubScripts -SkipVimQuery
							if ($Global:GetHostIP.Success -eq $true) {
								$HostIP = $Global:GetHostIP.HostIP
							}
						}
						if ($Global:GetVmHardware.Success -eq $true) {
								$VMHVersion = $Global:GetVmHardware.GuestVersion
								$VmHostversion = $Global:GetVmHardware.VmHostVersion
								$VmHost = $Global:GetVmHardware.VmHost
						}
						
						# Determine Results
						if ($Global:rebootRuntimes) {
							[string]$RebootRuntimes = $Global:rebootRuntimes
						}
						else
{
							[string]$RebootRuntimes = 'N/A'
						}
						if ($Global:RebootFailed -eq $true) {
							[string]$ScriptErrors += 'Failed Reboot  '
						}
						if ($RemoteLastPatchesLogfound -eq $false) {
							[string]$ScriptErrors += 'Failed Retrieving LastPatches Log  '
						}
						if ($LastPatchesLogEmpty -eq $true) {
							[string]$ScriptErrors += 'LastPatches Log Empty  '
						}
						if ($VmTUpdateSuccess -eq $false) {
							[string]$ScriptErrors += 'Failed Vmware Tools Update  '
							$VmTUpgraded = 'Error'
						}
						Elseif ($VmTUpdateSuccess -eq $true) {
							$VmTUpgraded = $true
						}
						else
{
							$VmTUpgraded = $false
						}
						if ($VmHUpdateSuccess -eq $false) {
							[string]$ScriptErrors += 'Failed Vmware Hardware Update  '
							$VmHUpgraded = 'Error'
						}
						Elseif ($VmHUpdateSuccess -eq $true) {
							$VmHUpgraded = $true
						}
						else
{
							$VmHUpgraded = $false
						}
						if ($IPConfigSuccess -eq $false) {
							[string]$ScriptErrors += 'Capture IPConfig Failed  '
						}
						if ($RunVBSSuccess -eq $false) {
							[string]$ScriptErrors += 'WUVBS Failed  '
						}

						if ($Failed -eq $false) {
							[boolean]$CompleteSuccess = $true
						}
						else
{
							[boolean]$CompleteSuccess = $false
						}

						# Set Default results for tasks not performed
						if (!$VmToolsOK) {
							[string]$VmToolsOK = 'N/A'
						}
						if (!$VmHardwareOK) {
							[string]$VmHardwareOK = 'N/A'
						}
						if (!$VmDataStore) {
							[string]$VmDataStore = 'N/A'
						}
						if (!$VmToolsVersion) {
							[string]$VmToolsVersion = 'N/A'
						}
						if (!$VMHVersion) {
							[string]$VMHVersion = 'N/A'
						}
						if (!$VmHostversion) {
							[string]$VmHostversion = 'N/A'
						}
						if (!$VmHost) {
							[string]$VmHost = 'N/A'
						}
						if (!$OSVersion) {
							[string]$OSVersion = 'Unknown'
						}
						if (!$OSArch) {
							[string]$OSArch = 'Unknown'
						}
						if (!$HostIP) {
							[string]$HostIP = 'Unknown'
						}
						if (!$DriveSize) {
							[string]$DriveSize = 'Unknown'
						}
						if (!$FreeSpace) {
							[string]$FreeSpace = 'Unknown'
						}
						if (!$ScriptErrors) {
							[string]$ScriptErrors = 'None'
						}

						# Update Logs
						$DateTimeF = Get-Date -format g
						$LogDataOutput += @(
							'',
							"OUTPUT:          [GATHERING DATA] Finished ($DateTimeF)"
							'',
							"OUTPUT:          [WRITING] Started ($DateTimeF)"
						)

						Get-Runtime -StartTime $JobStartTime #Results used Log Footer section too
						[string]$TaskResults = $ComputerName + ',' + $CompleteSuccess + ',' + $PatchingSuccess + ',' + $DiskCheckPassed + ',' + $VmToolsOK + ',' + $VmHardwareOK + ',' + $InstalledPatchesCount + ',' + $Global:RebootCount + ',' + $ConnectSuccess + ',' + $VmTUpgraded + ',' + $VmHUpgraded + ',' + $Global:GetRuntime.Runtime + ',' + $JobStartTime + ',' + $Global:GetRuntime.EndTimeF + ',' + $OSVersion + ',' + $OSArch + ',' + $HostIP + ',' + $DriveSize + ',' + $FreeSpace + ',' + $RebootRuntimes + ',' + $VmToolsVersion + ',' + $VMHVersion + ',' + $VmHost + ',' + $VmHostversion + ',' + $VmDataStore + ',' + $WuVBSExitCode + ',' + $ScriptErrors + ',' + $ScriptVersion + ',' + $ScriptHost + ',' + $UserName
						
						[int]$loopcount = 0
						[boolean]$errorfree = $false
						DO {
							$loopcount++
							Try {
								Add-Content -Path $ResultsTextFullName -Encoding Ascii -Value $TaskResults -ErrorAction Stop
								[boolean]$errorfree = $true
							}
							# IF FILE BEING ACCESSED BY ANOTHER SCRIPT CATCH THE TERMINATING ERROR
							Catch [System.IO.IOException] {
								[boolean]$errorfree = $false
								Sleep -Milliseconds 300
								# Could write to ScriptLog which error is caught
							}
							# ANY OTHER EXCEPTION
							Catch {
								[boolean]$errorfree = $false
								Sleep -Milliseconds 300
								# Could write to ScriptLog which error is caught
							}
						}
						# Try until writes to output file or 
						Until (($errorfree -eq $true) -or ($loopcount -ge '150'))
						
						# Update Logs
						$DateTimeF = Get-Date -format g
						$LogDataOutput += @(
							'',
							"OUTPUT:          [WRITING] Attempts = $loopcount ($DateTimeF)",
							'',
							"OUTPUT:          [WRITING] Finished ($DateTimeF)"
						)

						# Determine Patching Success
						$results = $null
						if ($PatchingSuccess -eq $true) {
							$results = 'Successfully Completed'
						}
						else
{
							$results = 'Failed Windows Patching'
						}
						
						# History Log Footer
						$Runtime = $Global:GetRuntime.Runtime
						$DateTimeF = Get-Date -format g
						$LogDataOutput += @(
							'',
							'',
							'',
							"WINDOWS PATCHING: $results",
							'',
							"JOB:             [ENDED] $DateTimeF",
							"Runtime:         $Runtime",
							'---------------------------------------------------------------------------------------------------------------------------------',
							''
						)
						$ScriptLogData += $LogDataOutput
						# Update History Log for Output Section
						Add-Content -Path $LocalHistoryLogFullName,$RemoteHistoryLogFullName -Encoding ASCII -Value $LogDataOutput
						Out-File -FilePath $LocalLatestLogFullName -Encoding ASCII -Force -InputObject $ScriptLogData
						Out-File -FilePath $RemoteLatestLogFullName -Encoding ASCII -Force -InputObject $ScriptLogData
					
					#endregion Generate Report

				} -ArgumentList $ComputerName,$SubScripts,$Assets,$ScriptVersion,$SkipVMToolsBool,$JobLogFullName,$vCenter,$MinFreeMB,$SkipDiskSpaceCheckBool,$UserDomain,$UserName,$ScriptHost,$FileDateTime,$SkipVMHardwareBool,$LogPath,$ResultsTextFullName,$UseAltViCredsBool,$ViCreds,$SkipAllVmwareBool | Out-Null
			
			#endregion Background Job
			# PROGRESS COUNTER
			$i++
		} #/Foreach Loop
	
	#endregion Job Loop

	Show-ScriptHeader -blanklines '4' -DashCount $DashCount -ScriptTitle $ScriptTitle
	# POST TOTAL HOSTS SUBMITTED FOR JOBS
	Show-ScriptStatus-JobsQueued -jobcount $TotalHosts
		
	#endregion Job Tasks
		
	#region Job Monitor
	
		Get-JobCount
		Set-WinTitle-JobCount -WinTitle_Input $Global:WinTitle_Input -jobcount $Global:getjobcount.JobsRunning
		
		# Job Monitoring function Will Loop Until Timeout or All are Completed
		Watch-Jobs -SubScripts $SubScripts -JobLogFullName $JobLogFullName -Timeout $JobQueTimeout -Activity "INSTALLING PATCHES" -WinTitle_Input $Global:WinTitle_Input
		
	#endregion Job Monitor

} #function End

#region Notes

<# Description
	function to check for pending reboot, check for minimum disk space, apply Windows patches, check/update Vmware Tools, check/update Vmware Hardware
#>

<# Author
	Levon Becker
	PowerShell.Guru@BonusBits.com
	http://wiki.bonusbits.com
#>

<# Dependents
	Install-Patches
#>

<# Shared Dependencies
ROOT
	Func_Get-Runtime
	Func_Cleanup_Jobs
	Func_Get-JobCount
	Func_Watch-Jobs
	MultiFunc_StopWatch
	MultiFunc_Set-WinTitle
	MultiFunc_Out-ScriptLog
	MultiFunc_Show-Script-Status
	
JOB LOOP
	Func_Get-Runtime
	Func_Get-PendingReboot
	Func_Get-DiskSpace
	Func_Get-VmHardware
	Func_Get-VmTools
	Func_Get-IPconfig
	Func_Restart-Host
	Func_Send-VMPowerOff
	Func_Send-VMPowerOn
	Func_Update-VmHardware
	Func_Update-VmTools
	Func_ConvertTo-ASCII
	Func_Get-HostIP
	Func_Get-OSVersion
#>

<# Private Dependencies
Job LOOP
	Multi_Write-Logs
		# Write-Logs-JobStart
		# Write-Logs-JobEnd
#>

<# Change Log
1.0.0 - 04/13/2011
	Created 
	Split off code from Windows-Patching_1.216
1.0.1 - 04/28/2011
	Cleaned up Info section.
	Added ConvertToFile-ASCII to convert the old Patch History files on the ComputerNames
	that are Unicode (Temporary, atleast until I can get a functioning Encoding check
	condition function).
	Fixed results from reboot function.
	Changed Break commands to Return.
	Fixed results variables / logic for vmtools upgrade
1.0.3 - 05/05/2011
	Changed Get-DiskSpace $minfree to $MinFreeMB
	Changed Get-DiskSpace results to match new PSObject output method
	Changed Get-IPConfig results to match new PSObject output method
1.0.4 - 05/06/2011
	Changed Vmtools section to used rewrote Update-VmTools sub script.
	Changed output to be true/false on sucessful upgrade of vmtools or vmhardware.
	Added rebootfailed logic to bail out to of anything after the failure then write logs at end.
1.0.5 - 05/08/2011
	Changed Restart-Host sections to not bail on fail, but set variable and skip following sections 
	if failed.
	Changed Disk-Check section and output a lot.  Inlcuding hpcok var added.
	Removed more Return statements to have script fall to end and write output only once.
1.0.6 - 05/08/2011 (WIP)
	Troubleshooting issue where Job is failing
1.0.7 - 05/09/2011 (WIP)
	Splitting out pieces that should be in the parent script.
1.0.8 - 05/13/2011
	Fixed History Log Append from LastPatches Log
	Added Adminhost and UserName to Output file
1.0.9 - 07/18/2011
	Renamed $Global:RestartHost.Runtime to $Global:RestartHost.RebootTime to fix missing reboot time output.
1.1.0 - 07/21/2011
	Adding reboot and try again if can't access logs.
	Commented out the $RebootRuntimes += @($Global:RestartHost.RebootTime) "adding to array" because it's not outputing to one field correctly (Fix later)
	Turned the many reboot sections into local function.
1.1.1 - 07/22/2011
	Adding debug output to script log
	Added MultiFunc_Out-ScriptLog to job script to output errors to the script log for debugging
1.1.2 - 10/02/2011
	Fixed Vmware Hardware Success reporting. It was a typing mistake with $VmHUpdateSuccess
	Added Vmtools, VmHardware and VmHost version to output
	Added $IPConfigSuccess = 'N/A'
	Fixed Reboot times variable to have a default 'N/A'
	Added Func_Get-OSVersion_1.0.0 function script to Job loop
	Added OS Version to output
1.1.3 - 10/05/2011
	Added ComputerName IP and Datastore to Output
1.1.4 - 10/09/2011
	Troubleshooting LastPatches Log issue
	Added Vmfound condition for VM info output
	Added $vCenter argument to Job and changed VM functions to include so only have to change it in Windows-Patching for different vCenter hostname
	Removed $hostfile variable (Not used)
	Changed Get-JobCount Output to PSObject variable for Wintitle updates
1.1.5 - 10/11/2011
	Added Get-HostIP for physical boxes
	Fixed Get-OSVersion variable (Unknown issue)
	Removed $ordfileList and $fileList
1.1.6 - 10/13/2011
	Changed reboot condition around line 565
	Fixed Args variable count was off from removing vcuser,creds etc.
	Added skip Vmware check/upgrades if patching failed
	Change rebootfailed variable to global
	Changed ComputerName log conditioning around
	Changed Patch rounds to 4
	Fixed Write-Logs-JobEnd to remove WIP and LastPatcheslogs plus update history logs (Was missing varible passing to function)
	Added Patching Success variable and conditioning
	Changed Update.vbs to new SearchDownloadInstall-WUA.vbs
	Removed Wuinstall.exe
1.1.7 - 10/14/2011
	Completely recoded the LastPatches log testing and copying
	Changed old vbs variable to delete old location back to 'Update.vbs'
1.1.8 - 11/04/2011
	Found Elseif instead of If typing mistake for reboot check after patching
	Changed Select-String to set variable as True or False when searching for reboot needed or no more patches needed
1.1.9 - 11/07/2011
	Testing updated Check Pending and Get-RegValue
1.2.0 - 11/0/2011
	Fixed wrong variable for checking if LocalLastPatchesLog is present
	Moved JobStartTime calc to just before output
	Added -UseAltViCreds $UseAltViCreds -ViCreds $ViCreds
	Added more statements for the VM section to the History logs
1.2.1 - 11/11/2011
	Changed to use Sub function that use Func_Connect-VIHost_1.0.3 to newer versions
	Bumped copylogloop up to 15 minutes (900 seconds)
	Bumped reboot in copylogloop to 5 minutes (300 seconds)
	Added logging to history log that it's being reboot for copylog not found after 5 minutes
1.2.2 - 11/21/2011
	Cleaned up code (regions mostly)
1.2.3 - 01/31/2012
	Changed Get-OSVersion from version 1 to 1.0.6.  Think I missed it in job when made changes. (Line 415)
1.2.4 - 02/02/2012
	Updated Remove-Jobs to 1.0.3
	Updated Watch-Jobs to 1.0.1
	Updated Get-JobCount to 1.0.2
	Increased Monitor Jobs Timeout to 9900 seconds = 2.5 hours
1.2.4 - 02/03/2012
	Added $TotalHosts Parameter for displaying Jobs Queued as total hosts and not just jobcount when it gets to end.
	Removed $CompleteSuccesslog
	Added Parameter settings
1.2.5 - 02/03/2012
	Removed all the separate failed log files now that it's in output they are not needed
	Removed Add-HostToLogFile function
	Removed Pending-Results function that isn't used anymore
	Add logic to Output file so it can deal with the output text file being open by other jobs.
1.2.5 - 02/07/2012
	Added Progress Bar for the Job Queueing phase (Foreach loop)
	Updated to MultiFunc_Show-Script-Status_1.0.2
	Added -Path and -Childpath to Join-path commands
	Remove Func_Check-Path_1.0.0
	Removed Job Monitor Timeout section at end and moved to Parent
1.2.7 - 02/09/2012
	Updated to Func_Invoke-PSExec_1.0.2
	Changed PSExec sections to new format
1.2.8 - 02/09/2012
	Cleaup UI output
1.2.8 - 02/10/2012
	Updated to Func_Restart-Host_1.0.6 (changed ComputerName to computer param)
	Converted Check Pending sections to local function
	Updated to Func_Invoke-PSExec_1.0.4 (logfile added)
	Added PSExec Log variables in job loop
1.2.9 - 02/10/2012
	Adjusted some timeouts
1.3.0 - 02/10/2012
	Updated to Func_Invoke-PSExec_1.0.5 (Try/catch)
	Removed PSexec process output to history logs
	Added reboot and retry of WU VBS if fails
	Removed Logfile from Invoke-PSExec
1.3.1 - 02/10/2012
	Added Show-ScriptHeader Subscript
	Added Show-ScriptHeader before Queueing jobs Display update
1.3.2 - 04/16/2012
	Changed version scheme
	Change spacecheck variable to $CheckFreeSpace switch
	Set Strict Variable Types at start of job "clear variables"
	Retired Multi_Write-Logs_1.0.3
1.3.3 - 04/16/2012
	Changed CheckFreeSpace to $SkipDiskSpaceCheck
	Changed vmtu and vmhu boolean to switches SkipVMHardware and SkipVMTools
	Changed UseAltViCreds to UseAltViCredsBool boolean
1.3.4 - 04/16/2012
	Changed log output sections to arrays to reduce access count to log files and reduce syntax.
		May change to gather all the log output to one array and write at end.
1.3.5 - 04/19/2012
	Removed a lot of history log updates
	Used Trim to remove blank lines from SubFunction results
1.3.6 - 04/20/2012
	Working on Vmtools upgrade wait issue
	Changed History Log updates to be gathered up in an array and output at end to reduce file accessing.
1.3.9 - 04/23/2012
	Moved Output columns around and renamed some
1.4.2 - 04/30/2012
	Added RunAs32 switch to Background job! wow how did I miss that as a solution for the PowerCLI bug.
	Changed UseAltViCreds to UseAltViCredsBool
1.4.4 - 05/03/2012
	Tons of variable and parameter naming changes
1.4.5 - 05/08/2012
	Switched to Get-HostIP 1.0.5
1.4.6 - 05/08/2012
	Added JobQueTimeout parameter
	Added Remove-Jobs to each loop to maintain a better Jobs Left nummber and stay out of the Job Throttle loop more.
	Switched to Watch-Jobs 1.0.3
1.4.7 - 05/15/2012
	Added Connect Success for Results
	Renamed SearchDownloadInstall-WUA VB script to Install-Patches
	Added new VBTemp folder
	Repurposed Latest log folder to actually have the latest History Log Info.
	Added the logic needed for the new Latest Log file
	Rearranged Results columns
	Added ScriptErrors to results
	Added back endtime to results
	Added extra Get-VmTools at end of update
	Added VmToolsUpdateSuccess to VmTools section
1.4.8 - 05/16/2012
	Switched to Get-OSVersion 1.0.9
#>

<# To Do List
	x 07/21/2011: Fix Reboot times to output all in one field?
	07/22/2011: Disk Space check fail is showing passed = Unknown
	07/22/2011: 4 rounds of empty patching data in history file ?? 
	07/22/2011: Increase information to Script Log i.e. get-variables etc.
#>

#endregion Notes
